package net.hands.common;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Random;

import javax.imageio.ImageIO;

import net.hands.common.logger.Log;
import net.hands.common.logger.LogFactory;

/**
 * 说明:图片工具类
 * <br>
 * <p>这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。</p>
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
public abstract class ImageUtils {
	static Log log = LogFactory.getLogger(ImageUtils.class);
   /**
    * 字符常量 0-9A-Za-z
    */
	public static final String code = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   /**
    * 随机数
    */
	private static Random random = new Random();
   /**
   * 说明:获得随机颜色
   * @param fc 随机数
   * @param bc 随机数
   * @return Color
   * @update 2012-9-24 下午1:55:56
    */
	public static Color getRandColor(int fc, int bc) {
		fc = Math.min(fc, 255);
		bc = Math.min(bc, 255);
		final int r = fc + random.nextInt(bc - fc);
		final int g = fc + random.nextInt(bc - fc);
		final int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}
   /**
    * 
   * 说明:随机验证码
   * @param outputStream 输出流
   * @return String    
   * @throws IOException
   * @update 2012-9-24 下午1:56:46
    */
	public static String genCode(final OutputStream outputStream) throws IOException {
		return genCode(90, 38, outputStream);
	}
   /**
   * 说明:随机验证码
   * @param width 宽度
   * @param height 高度
   * @param outputStream 输出流
   * @return String
   * @throws IOException
   * @update 2012-9-24 下午1:57:14
    */
	public static String genCode(final int width, final int height, final OutputStream outputStream)
			throws IOException {
		//缓存图片
		final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		//2d绘图
		final Graphics2D g = bi.createGraphics();
      //线性颜色渐变模式
		final GradientPaint gp = new GradientPaint(0, 0, Color.WHITE, width, height, getRandColor(
				120, 200), false);
		//绘图设置颜色渐变
		g.setPaint(gp);
		//填充
		g.fillRect(0, 0, width, height);
		
		for (int i = 0; i < 50; i++) {
			g.setColor(getRandColor(210, 220));
			g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width),
					random.nextInt(height));//画50条线
		}
		g.setColor(Color.GRAY);//灰色
		g.drawRect(0, 0, width - 1, height - 1);//绘制一个矩形边框

		final Font font = new Font("comic sans ms", Font.BOLD, 24);//采用字体
		g.setFont(font);//设置字体
      //字体规格对象
		final FontMetrics metrics = g.getFontMetrics();
		//字符宽度
		int stringWidth = 0;
		final char[] text = new char[4];
		final int[] textWidth = new int[4];
		for (int i = 0; i < 4; i++) {
			final int j = random.nextInt(code.length());//随机4个字符
			text[i] = code.charAt(j);
			textWidth[i] = metrics.charWidth(text[i]);
			stringWidth += textWidth[i];
		}
		int posX = (width - stringWidth) / 2;  //x坐标
		final int posY = (height - metrics.getHeight()) / 2 + metrics.getAscent();//y坐标
		for (int i = 0; i < text.length; i++) {
			g.setColor(getRandColor(50, 120));//随机颜色
			g.drawString(Convert.toString(text[i]), posX, posY);
			posX += textWidth[i];
		}
		ImageIO.write(bi, "png", outputStream);//输出图形
		return Convert.toString(text);//返回文字内容
	}
   /**
   * 说明:图片自适应处理
   * @param inputStream 输入流
   * @param width   宽度
   * @param height  高度
   * @param outputStream 输出流
   * @throws IOException
   * @update 2012-9-24 下午2:13:56
    */
	public static void thumbnail(final InputStream inputStream, final int width, final int height,
			final OutputStream outputStream) throws IOException {
		thumbnail(inputStream, width, height, outputStream, "png");
	}
   /**
   * 说明:图片自适应处理
   * @param inputStream 输入流
   * @param width 宽度
   * @param height 高度
   * @param outputStream 输出流
   * @param filetype 文件类型
   * @throws IOException
   * @update 2012-9-24 下午2:15:47
    */
	public static void thumbnail(final InputStream inputStream, final int width, final int height,
			final OutputStream outputStream, final String filetype) throws IOException {
		thumbnail(inputStream, width, height, false, outputStream, filetype);
	}
   /**
   * 说明:图片自适应处理
   * @param inputStream  输入流
   * @param width    宽度
   * @param height   高度
   * @param stretch  是否拉伸
   * @param outputStream 输出流
   * @param filetype  文件类型
   * @throws IOException 
   * @update 2012-9-24 下午2:15:54
    */
	public static void thumbnail(final InputStream inputStream, final int width, final int height,
			final boolean stretch, final OutputStream outputStream, final String filetype)
			throws IOException {
		//宽度 高度
		int w, h;
		try {
			if (width == 0 && height == 0) {//如果宽度和高度为0
				//输入流东西拷贝到输出流中
				IoUtils.copyStream(inputStream, outputStream);
				return;//结束
			}
			//缓冲图片
			final BufferedImage sbi = ImageIO.read(inputStream);
		   
			if (sbi == null) {//图片缓冲为空结束
				return;
			}
			if (width == 0 || height == 0) {//宽度为0或高度为0
				w = sbi.getWidth();//获得图片宽度,
				h = sbi.getHeight();//获得图片高度
			} else if (!stretch) {//是否拉伸
				final double d = (double) width / (double) height;
				final double d0 = (double) sbi.getWidth() / (double) sbi.getHeight();
				if (d < d0) {
					w = width;
					h = (int) (width / d0);
				} else {
					w = (int) (height * d0);
					h = height;
				}
			} else {
				w = width;
				h = height;
			}
			//图像，该图像具有打包成整数像素的 8 位 RGBA 颜色分量
			final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
			//2维绘图
			final Graphics2D g = bi.createGraphics();
			//绘sbi图
			if (w != width) {
				g.drawImage(sbi, Math.abs(w - width) / 2, 0, w, h, null);
			} else if (h != height) {
				g.drawImage(sbi, 0, Math.abs(h - height) / 2, w, h, null);
			} else {
				g.drawImage(sbi, 0, 0, w, h, null);
			}
			g.dispose();//释放它所使用的所有系统资源
			//写入此图
			ImageIO.write(bi, filetype, outputStream);
		} finally {
			outputStream.close();
		}
	}
   /**
   * 说明:判断url获得是否为图片
   * @param url url地址
   * @return boolean
   * @throws IOException
   * @update 2012-9-24 下午2:16:06
    */
	public static boolean isImage(final URL url) throws IOException {
		final InputStream inputStream = url.openStream();
		try {
			return ImageIO.read(inputStream) != null;
		} finally {
			inputStream.close();
		}
	}
}
